﻿using Glorysoft.Auto.Xfw;
using Glorysoft.EAP.Contracts.MESClient;
using Glorysoft.EAP.Contracts.MESClient.Models;
using Glorysoft.EAP.Core;
using Glorysoft.EAP.Core.Entities;
using Glorysoft.EAP.Core.Enums;
using Glorysoft.EAP.EAPwell.web.entity;
using Glorysoft.EAP.RC.EAPClient;
using Glorysoft.EAP.RC.MES;
using MathNet.Numerics.IntegralTransforms;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Graph;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.Util;
using Org.BouncyCastle.Asn1.Tsp;
using Org.BouncyCastle.Ocsp;
using Serilog.Core;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using NCalc;
using NPOI.SS.Formula;


namespace Glorysoft.EAP.EAPwell.web.controller
{
    public class WaferController : ControllerBase
    {
        protected static Logger TrackoutLogger = XfwContext.LogManager.Create("TrackOutLogger");
        protected readonly IConfiguration Config = XfwContext.Configuration as IConfiguration;

        EAPClientService ClientService = new EAPClientService();
        [Route("wafer/end")]
        [HttpPost]
        public List<string> waferEndReport([FromBody] JObject jo)
        {
            try
            {

                var waferId = (string)jo["waferId"];
                var passNo = (string)jo["passNo"];
                var p50Median = (string)jo["p50Median"];
                TrackoutLogger.Information($"收到wafer:{waferId} PASSNO: {passNo}");
                //STEP 1 ===>>判断这次STDF上报是否应该被处理
                //1、更新程序导致没有进站缓存跳过处理。
                //2、waferId不在历史作业批次内跳过处理
                //3、waferId对应测试开始时间小于缓存

                if (string.IsNullOrEmpty(waferId) || string.IsNullOrEmpty(passNo))
                {
                    TrackoutLogger.Information($"参数为空跳过处理");
                    return null;
                }
                if (Dict.Current.TrackOutLotQueue.Count == 0)
                {
                    TrackoutLogger.Information($"出帐队列Lot数量为0，忽略请求");
                    return null;
                }
                string lotId = "";
                Wafer wafer1 = null; ;
                foreach (var item in Dict.Current.TrackOutLotQueue)
                {
                    var lotInfo1 = item.Value;
                    wafer1 = new Wafer();
                    //优化waferid识别为空的情况
                    wafer1 = lotInfo1.waferList.FirstOrDefault(o => !string.IsNullOrEmpty(o.waferId) && (o.waferId == waferId || o.waferId.Substring(0, o.waferId.Length - 3) == waferId));
                    if (wafer1 == null)
                    {
                        continue;
                    }
                    else
                    {
                        lotId = item.Key;
                        break;
                    }
                }

                if (wafer1 == null)
                {
                    TrackoutLogger.Information("该wafer对应Lot 未使用EAP进站" + waferId);
                    //ClientService.ShowMessage("该wafer 未使用EAP进站{}", waferId);
                    return null;
                }
                if (string.IsNullOrEmpty(lotId))
                {
                    TrackoutLogger.Information(string.Format("缓存中没有找到批次号" + waferId));
                    ClientService.ShowMessage("缓存中没有找到批次号{}", waferId);
                    return null;
                }
                var lotInfo = Dict.Current.TrackOutLotQueue[lotId];

                if (wafer1.processFlag == "Y" && wafer1.passNo == passNo)
                {
                    TrackoutLogger.Information(string.Format("相同事件上报，忽略处理"));
                    return getWaitWaferList(lotInfo.waferList);
                }
                ClientService.ShowMessage("EAP>设备上报WaferId：{0} 测试结束,PassDie数量：{1}", waferId, passNo);
                wafer1.processFlag = "Y";
                wafer1.passNo = passNo;
                wafer1.processState = ProcessState.ProcessEnd.ToString();


                if (!string.IsNullOrEmpty(p50Median))
                {
                    wafer1.p50Median = p50Median;
                };
                // monitor批次执行 切换机台状态或上报MES
                if (lotInfo.monitorLotFlag)
                {
                    ClientService.ShowMessage("EAP>开始计算Monitor 测试项");
                    List<Die> dieList = new List<Die>();
                    if (jo["dieList"] != null)
                    {
                        dieList = JsonConvert.DeserializeObject<List<Die>>(jo["dieList"].ToString());
                        ClientService.ShowMessage("EAP>解析所有Die测试结果完成");
                    }
                    else
                    {
                        ClientService.ShowMessage("EAP>解析所有Die测试结果失败");
                        return null;
                    }
                    SMECMESClient mesClient = new SMECMESClient();
                    JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
                    jsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore;
                    wafer1.Summaries = new List<Summary>();
                    wafer1.Summaries = JsonConvert.DeserializeObject<List<Summary>>(jo["testItemSummaryList"].ToString(), jsonSerializerSettings);
                    wafer1.yield = jo["yield"].ToString();
                    //Auto Monitor不用判断批次结束，直接上报
                    //Step 1 判断是否存在Fail项目 存在则直接切换机台状态
                    JObject config = lotInfo.monitorConfig;
                    //校验良率
                    var holdMessage = "";
                    var productMonitorLotList = JsonConvert.DeserializeObject<List<ProductMonitorLot>>(config["spcLotList"].ToString(), jsonSerializerSettings);
                    ProductMonitorLot lotConfig = productMonitorLotList.FirstOrDefault(o => o.waferId == wafer1.waferId);
                    if (lotConfig != null)
                    {
                        ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}良率{wafer1.yield},标准值{lotConfig.yield}");
                        if (lotConfig.yield != null && double.Parse(wafer1.yield) < double.Parse(lotConfig.yield))
                        {
                            ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}良率{wafer1.yield}小于标准值{lotConfig.yield}");
                            holdMessage += $"AutoMonito Wafer:{wafer1.waferId}良率{wafer1.yield}小于标准值{lotConfig.yield}";
                            TrackoutLogger.Information($"AutoMonito Wafer:{wafer1.waferId}良率{wafer1.yield}小于标准值{lotConfig.yield}");
                        }
                    }
                    else
                    {
                        ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}良率{wafer1.yield},标准值未配置，SPC上报失败");
                        return null;
                    }
                    //校验测试项，每片都校验
                    var productMonitorItemList = JsonConvert.DeserializeObject<List<ProductMonitorItem>>(config["spcMonitorItemList"].ToString(), jsonSerializerSettings);
                    var productMonitorChartList = JsonConvert.DeserializeObject<List<ProductMonitorChart>>(config["spcChartList"].ToString(), jsonSerializerSettings);
                    var spcWaferOffsetList = JsonConvert.DeserializeObject<List<SpcOffsetWafer>>(config["spcOffsetWaferList"].ToString(), jsonSerializerSettings);
                    var spcEquipmentOffsetList = JsonConvert.DeserializeObject<List<SpcOffsetEquipment>>(config["spcOffsetEquipmentList"].ToString(), jsonSerializerSettings);
                    ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId},Monitor测试项数量{productMonitorItemList.Count},SPC Chart数量{productMonitorChartList.Count}");
                    List<UploadData> uploadDatas = new List<UploadData>();
                    int needReportChartCount = 0;
                    foreach (var item in productMonitorItemList)
                    {
                        int addCount = 0;
                        if (!string.IsNullOrEmpty(item.avgMesKey))
                        {
                            addCount = 1;
                            if (item.avgMesKey.Contains(";"))
                            {
                                addCount = item.avgMesKey.Split(";").Length;

                            }
                        }
                        needReportChartCount += addCount;
                    }


                    foreach (var item in productMonitorItemList)
                    {
                        //以S_开头的测试项，取指定坐标的Die结果，并且Chart名称与Key名称相同 。
                        if (item.itemName.StartsWith("S_") && !string.IsNullOrEmpty(item.avgMesKey))
                        {
                            var chartTemp = productMonitorChartList.FirstOrDefault(o => string.Equals(o.k2ParaName, item.itemName, StringComparison.OrdinalIgnoreCase));
                            if (chartTemp == null)
                            {
                                chartTemp = productMonitorChartList.FirstOrDefault(o => string.Equals(o.jobName.Split("-")[o.jobName.Split("-").Length - 1], item.itemName, StringComparison.OrdinalIgnoreCase));
                                if (chartTemp == null)
                                {
                                    ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}Chart不存在{item.itemName}，无法收值");
                                    TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}Chart不存在{item.itemName}，无法收值");
                                    return null;
                                }
                            }
                            string key = item.avgMesKey.Replace("(", "").Replace(")", "");
                            int x = int.Parse(key.Split(",")[0]);
                            int y = int.Parse(key.Split(",")[1]);
                            //寻找对应X Y 的测试项值
                            foreach (var item1 in dieList)
                            {
                                TestItem result = null;
                                if (item1.xCoord == x && item1.yCoord == y)
                                {
                                    try
                                    {
                                        result = item1.testItemList.First(testCase => string.Equals(testCase.name, item.itemName.Remove(0, 2), StringComparison.OrdinalIgnoreCase));
                                    }
                                    catch (Exception e)
                                    {
                                        ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}坐标:{x}:{y}下未找到测试项{item.itemName}，无法收值");
                                        TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}坐标:{x}:{y}下未找到测试项{item.itemName}，无法收值");
                                        continue;
                                    }
                                    if (result == null)
                                    {
                                        ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}坐标:{x}:{y}下未找到测试项{item.itemName}，无法收值");
                                        TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}坐标:{x}:{y}下未找到测试项{item.itemName}，无法收值");
                                        return null;
                                    }
                                    //判断是否超规格
                                    if (item.avgLowerLimit != 0 && result.result < item.avgLowerLimit)
                                    {
                                        ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}坐标：{x},{y}测试项{item.itemName}结果{result.result}小于最小值{item.avgLowerLimit}");
                                        holdMessage += $"AutoMonitor Wafer:{wafer1.waferId}坐标：{x},{y}测试项{item.itemName}结果{result.result}小于最小值{item.avgLowerLimit}";
                                        TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}坐标：{x},{y}测试项{item.itemName}结果{result.result}小于最小值{item.avgLowerLimit}");
                                    }
                                    if (item.avgUpperLimit != 0 && result.result > item.avgUpperLimit)
                                    {
                                        ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}坐标：{x},{y}测试项{item.itemName}结果{result.result}大于最大值{item.avgUpperLimit}");
                                        holdMessage += $"AutoMonitor Wafer:{wafer1.waferId}坐标：{x},{y}测试项{item.itemName}结果{result.result}大于最大值{item.avgUpperLimit}";
                                        TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}坐标：{x},{y}测试项{item.itemName}结果{result.result}大于最大值{item.avgUpperLimit}");
                                    }
                                    UploadData uploadData = CreateUploadData(chartTemp, result.result, lotInfo, productMonitorLotList, wafer1.waferId, spcWaferOffsetList, spcEquipmentOffsetList);
                                    uploadDatas.Add(uploadData);
                                }
                            }
                        }
                        else
                        {
                            //测试项平均值计算
                            var itemSummary = wafer1.Summaries.FirstOrDefault(o => string.Equals(o.testName, item.itemName, StringComparison.OrdinalIgnoreCase));
                            if (itemSummary == null)
                            {
                                ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}测试项中不存在{item.itemName}，比对失败");
                                mesClient.HoldEqpt(Dict.Current.TesterID, Dict.Current.TesterID, $"AutoMonitor Wafer:{wafer1.waferId}测试项中不存在{item.itemName}，比对失败", lotInfo.userName, Dict.Current.lotInfo.facilityId);
                                TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}测试项中不存在{item.itemName}，比对失败");
                                return null;
                            }
                            if (item.avgLowerLimit != 0 && itemSummary.average < item.avgLowerLimit)
                            {
                                ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果平均值{itemSummary.average}小于最小值{item.avgLowerLimit}");
                                holdMessage += $"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果平均值{itemSummary.average}小于最小值{item.avgLowerLimit}";
                                TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果平均值{itemSummary.average}小于最小值{item.avgLowerLimit}");
                            }
                            if (item.avgUpperLimit != 0 && itemSummary.average > item.avgUpperLimit)
                            {
                                ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果平均值{itemSummary.average}大于最大值{item.avgUpperLimit}");
                                holdMessage += $"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果平均值{itemSummary.average}大于最大值{item.avgUpperLimit}";
                                TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果平均值{itemSummary.average}大于最大值{item.avgUpperLimit}");
                            }
                            if (item.stdevLowerLimit != 0 && itemSummary.standardDeviation < item.stdevLowerLimit)
                            {
                                ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果方差{itemSummary.standardDeviation}小于最小值{item.stdevLowerLimit}");
                                holdMessage += $"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果方差{itemSummary.standardDeviation}小于最小值{item.stdevLowerLimit}";
                                TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果方差{itemSummary.standardDeviation}小于最小值{item.stdevLowerLimit}");
                            }
                            if (item.stdevUpperLimit != 0 && itemSummary.standardDeviation > item.stdevUpperLimit)
                            {
                                ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果方差{itemSummary.standardDeviation}大于最大值{item.stdevUpperLimit}");
                                holdMessage += $"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果方差{itemSummary.standardDeviation}大于最大值{item.stdevUpperLimit}";
                                TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}测试项{item.itemName}结果方差{itemSummary.standardDeviation}大于最大值{item.stdevUpperLimit}");
                            }
                            //全部比对通过判断是否需要收值 先只收平均值
                            if (!string.IsNullOrEmpty(item.avgMesKey))
                            {
                                //如果包含分号，则存在多个收值chart
                                if (item.avgMesKey.Contains(";"))
                                {
                                    string[] mesKey = item.avgMesKey.Split(';');
                                    // is sample die? 
                                    foreach (string key in mesKey)
                                    {
                                        //收指定die的测试结果
                                        if (key.Contains("("))
                                        {
                                            string chartKey = key.Split("(")[0];
                                            int x = int.Parse(key.Split("(")[1].Split(",")[0]);
                                            int y = int.Parse(key.Split("(")[1].Split(",")[1].Replace(")", ""));
                                            var chartTemp = productMonitorChartList.FirstOrDefault(o => string.Equals(o.k2ParaName, chartKey, StringComparison.OrdinalIgnoreCase));
                                            //寻找对应X Y 的测试项值
                                            foreach (var item1 in dieList)
                                            {
                                                if (item1.xCoord == x && item1.yCoord == y)
                                                {

                                                    try
                                                    {
                                                        var result = item1.testItemList.First(testCase => string.Equals(testCase.name, item.itemName, StringComparison.OrdinalIgnoreCase));
                                                        UploadData uploadData = CreateUploadData(chartTemp, result.result, lotInfo, productMonitorLotList, wafer1.waferId, spcWaferOffsetList, spcEquipmentOffsetList);
                                                        uploadDatas.Add(uploadData);
                                                    }
                                                    catch (Exception ex)
                                                    {

                                                        TrackoutLogger.Error("", ex);
                                                        continue;
                                                    }

                                                }

                                            }
                                        }
                                        //收平均值
                                        else
                                        {
                                            var chart = productMonitorChartList.FirstOrDefault(o => string.Equals(o.k2ParaName, key, StringComparison.OrdinalIgnoreCase));
                                            UploadData uploadData = CreateUploadData(chart, itemSummary.average, lotInfo, productMonitorLotList, wafer1.waferId, spcWaferOffsetList, spcEquipmentOffsetList);
                                            uploadDatas.Add(uploadData);
                                        }
                                    }



                                }
                                //收平均值
                                else
                                {
                                    var chart = productMonitorChartList.FirstOrDefault(o => string.Equals(o.jobName.Split("-")[o.jobName.Split("-").Length - 1], item.avgMesKey, StringComparison.OrdinalIgnoreCase));
                                    if (chart != null)
                                    {

                                        UploadData uploadData = CreateUploadData(chart, itemSummary.average, lotInfo, productMonitorLotList, wafer1.waferId, spcWaferOffsetList, spcEquipmentOffsetList);
                                        uploadDatas.Add(uploadData);
                                    }
                                    else
                                    {

                                        chart = productMonitorChartList.FirstOrDefault(o => string.Equals(o.k2ParaName, item.avgMesKey, StringComparison.OrdinalIgnoreCase));
                                        if (chart != null)
                                        {
                                            UploadData uploadData = CreateUploadData(chart, itemSummary.average, lotInfo, productMonitorLotList, wafer1.waferId, spcWaferOffsetList, spcEquipmentOffsetList);
                                            uploadDatas.Add(uploadData);
                                        }
                                        else
                                        {
                                            TrackoutLogger.Information($"AutoMonitor Chart Key Exception:{item.avgMesKey}");
                                        }
                                    }
                                }
                            }
                        }




                    }
                    ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId} SPC数据解析完成，上报Chart数量{uploadDatas.Count},需要上报数量{needReportChartCount}");
                    // 找出旧集合中有但新集合中没有的学生（根据姓名判断）
                    var missingCharts = FindMissingChartsByName(
                        productMonitorChartList,
                        uploadDatas,
                        spcChart => spcChart.jobName,    // 从旧集合对象中提取姓名
                        uploadData => uploadData.jobBaseInfo.jobName     // 从新集合对象中提取姓名
                    );
                    if (uploadDatas.Count != needReportChartCount)
                    {
                        string unUploadName = "";
                        
                    }
                    string upload = JsonConvert.SerializeObject(uploadDatas);
                    mesClient.uploadNonRTData(Dict.Current.lotInfo.facilityId, lotInfo.userName, Dict.Current.TesterID, upload);
                    ClientService.ShowMessage($"AutoMonitor Wafer:{wafer1.waferId} SPC数据上抛成功");
                    TrackoutLogger.Information($"AutoMonitor Wafer:{wafer1.waferId}SPC数据上抛成功");

                    if (!string.IsNullOrEmpty(holdMessage))
                    {
                        mesClient.HoldEqpt(Dict.Current.TesterID, Dict.Current.TesterID, holdMessage.Length > 200 ? holdMessage.Substring(0, 200) : holdMessage, lotInfo.userName, Dict.Current.lotInfo.facilityId);
                    }
                    Dict.Current.TrackOutLotQueue.Remove(lotId);
                }

            }

            catch (Exception e)
            {
                ClientService.ShowMessage($"WaferEnd异常" + e.StackTrace);
                TrackoutLogger.Information("WaferEnd异常：" + e.StackTrace);
            }
            return null;
        }

        public static IEnumerable<TOld> FindMissingChartsByName<TOld, TNew>(
        IEnumerable<TOld> oldCollection,
        IEnumerable<TNew> newCollection,
        Func<TOld, string> oldNameSelector,
        Func<TNew, string> newNameSelector)
        {
            // 获取新集合中所有名称，转换为小写以实现不区分大小写的比较
            var newNames = new HashSet<string>(
                newCollection.Select(newNameSelector).Select(name => name.ToLowerInvariant())
            );

            // 找出旧集合中名称不在新集合中的元素
            return oldCollection.Where(oldItem =>
                !newNames.Contains(oldNameSelector(oldItem).ToLowerInvariant())
            );
        }

        private UploadData CreateUploadData(ProductMonitorChart chart, Double value, LotInfo lotInfo, List<ProductMonitorLot> productMonitorLots, string waferID, List<SpcOffsetWafer> waferOffsetList, List<SpcOffsetEquipment> equipmentOffsetList)
        {
            var waferOffset = waferOffsetList.FirstOrDefault(o => o.jobName == chart.jobName);
            if (waferOffset != null)
            {
                Expression waferOffsetExpression = new Expression(waferOffset.formula);
                waferOffsetExpression.Parameters["x"] = value;
                value = (double)waferOffsetExpression.Evaluate();
            }

            var equipmentOffser = equipmentOffsetList.FirstOrDefault(o => o.jobName == chart.jobName);
            if (equipmentOffser != null)
            {
                Expression equipmentOffsetExpression = new Expression(equipmentOffser.formula);
                equipmentOffsetExpression.Parameters["x"] = value;
                value = (double)equipmentOffsetExpression.Evaluate();
            }

            UploadData uploadData = new UploadData();
            JobBaseInfo jobBaseInfo = new JobBaseInfo();
            jobBaseInfo.area = chart.area;
            jobBaseInfo.formulaPara = chart.formulaPara;
            jobBaseInfo.formulaType = chart.formulaType;
            jobBaseInfo.jobId = chart.jobId;
            jobBaseInfo.jobName = chart.jobName;
            chart.nonRtKey = chart.nonRtKey.TrimEnd(';').Replace(";", "\\");
            jobBaseInfo.nonRTKey = chart.nonRtKey;

            jobBaseInfo.subgroupSize = 1;
            jobBaseInfo.deriveChartName = null;
            jobBaseInfo.deriveChartId = "";
            jobBaseInfo.deriveNonRTKey = "";
            jobBaseInfo.valueType = "POST";
            uploadData.jobBaseInfo = jobBaseInfo;
            uploadData.unitList = new List<Unit>();

            jobBaseInfo.lotId = productMonitorLots.FirstOrDefault(o => o.waferId == waferID).monitorLotId;
            string slot = productMonitorLots.FirstOrDefault(o => o.waferId == waferID).position;
            if (int.Parse(slot) < 10)
            {
                slot = "0" + slot;
            }
            Unit unit = new Unit();
            unit.unitId = productMonitorLots.FirstOrDefault(o => o.waferId == waferID).monitorLotId + "#" + slot;
            unit.valueList = new List<double>();
            unit.valueList.Add(value);
            uploadData.unitList.Add(unit);

            return uploadData;
        }

        private List<string> getWaitWaferList(List<Wafer> wafers)
        {
            List<string> strings = new List<string>();
            foreach (Wafer wafer in wafers)
            {
                if (wafer.processFlag != "Y")
                {
                    strings.Add(wafer.waferId);
                }

            }
            return strings;
        }


    }
}
